/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ScriptEditor.java
 *
 * Created on Oct 2, 2010, 12:03:00 PM
 */

package net.worlds.component;

import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import net.worlds.ui.UI;
import javax.swing.JEditorPane;
import net.worlds.AssetManager;
import net.worlds.WorldsException;
import net.worlds.Main;
import net.worlds.object.HiddenScript;
import net.worlds.object.Script;
import se.krka.kahlua.luaj.compiler.LuaCompiler;
import se.krka.kahlua.vm.LuaClosure;
import se.krka.kahlua.vm.LuaState;

/**
 *
 * @author Jacob Morgan
 */
public class ScriptEditor extends javax.swing.JPanel {
    private Script script;
    private ImageIcon checkIcon;
    private ImageIcon xIcon;
    private final Color green = new Color(0, 102, 0);
    private final Color red = new Color(102, 0, 0);
    final JEditorPane codeEditor = new JEditorPane();
    private boolean scriptChanged = true;
    private Thread compileThread;
    private boolean running = true;
    /** Creates new form ScriptEditor */
    public ScriptEditor(Script s) throws WorldsException {
        initComponents();
        script = s;
        scriptLabel.setText("Editing: "+script);
        codeEditor.setEditable(true);
        codeEditor.setEnabled(true);
        scroller.setViewportView(codeEditor);
        codeEditor.setContentType("text/lua");
        scroller.validate();
        codeEditor.setText(s.getStringProp("Source"));
        compileThread = new Thread(new ScriptTester());
        compileThread.start();
        codeEditor.addKeyListener(new KeyListener()
        {

            public void keyTyped(KeyEvent e) {
            }

            public void keyPressed(KeyEvent e) {
                scriptChanged = true;
            }

            public void keyReleased(KeyEvent e) {
            }
            
        });
        try {
            checkIcon = new ImageIcon(AssetManager.loadImage("check.png", "check.png"));
            xIcon = new ImageIcon(AssetManager.loadImage("delete.png", "delete.png"));
            statusLabel.setIcon(checkIcon);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    public ScriptEditor(Script s, String params) throws WorldsException
    {
        this(s);
        paramsLabel.setText(params);
    }

    public void setScript(Script s)
    {
        script = s;
        scriptLabel.setText("Editing: "+script);
        try {
            codeEditor.setText(script.getStringProp("Source"));
        } catch (WorldsException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    public void setParams(String p)
    {
        paramsLabel.setText(p);
    }
    
    private String compileTest()
    {
        LuaState s = Main.getScriptContext().newState(script.world);
        s.getEnvironment().rawset("script", this);
        try {
            LuaClosure c = LuaCompiler.loadstring(codeEditor.getText(), script.toString(), s.getEnvironment());
        } catch (Exception ex) {
            if(ex.getMessage() != null)
                return ex.getMessage();
            else
                return ex.toString();
        }
        return null;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        topBar = new javax.swing.JPanel();
        scriptLabel = new javax.swing.JLabel();
        closeButton = new javax.swing.JButton();
        paramsLabel = new javax.swing.JLabel();
        scroller = new javax.swing.JScrollPane();
        topBar2 = new javax.swing.JPanel();
        statusLabel = new javax.swing.JLabel();

        scriptLabel.setText("Editing:");

        closeButton.setText("Close");
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        paramsLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        paramsLabel.setText(" ");

        javax.swing.GroupLayout topBarLayout = new javax.swing.GroupLayout(topBar);
        topBar.setLayout(topBarLayout);
        topBarLayout.setHorizontalGroup(
            topBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, topBarLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scriptLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 207, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(paramsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 263, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(closeButton)
                .addContainerGap())
        );
        topBarLayout.setVerticalGroup(
            topBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(closeButton)
                .addComponent(paramsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE)
                .addComponent(scriptLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE))
        );

        statusLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        statusLabel.setForeground(new java.awt.Color(0, 102, 0));
        statusLabel.setIcon(checkIcon);
        statusLabel.setText("No errors");

        javax.swing.GroupLayout topBar2Layout = new javax.swing.GroupLayout(topBar2);
        topBar2.setLayout(topBar2Layout);
        topBar2Layout.setHorizontalGroup(
            topBar2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topBar2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusLabel)
                .addContainerGap(421, Short.MAX_VALUE))
        );
        topBar2Layout.setVerticalGroup(
            topBar2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, topBar2Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(statusLabel)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(topBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(topBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(scroller, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(topBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(scroller, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(topBar2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
        try {
            script.setProp("Source", codeEditor.getText(), true);
        } catch (WorldsException ex) {
            ex.printStackTrace();
        }
        running = false;
        if(script instanceof HiddenScript)
        {
            if(codeEditor.getText().trim().split("\n").length > 0)
                Main.runInMainThread(new Runnable()
                {
                    public void run() {
                        try {
                            script.run();
                        } catch (WorldsException ex) {
                            ex.printStackTrace();
                        }
                    }
                });
            else
            {
                Main.runInMainThread(new Runnable()
                {
                    public void run() {
                        try {
                            script.remove();
                        } catch (WorldsException ex) {
                            ex.printStackTrace();
                        }
                    }
                });
            }
        }
        UI.closeScript();
    }//GEN-LAST:event_closeButtonActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton closeButton;
    private javax.swing.JLabel paramsLabel;
    private javax.swing.JLabel scriptLabel;
    private javax.swing.JScrollPane scroller;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JPanel topBar;
    private javax.swing.JPanel topBar2;
    // End of variables declaration//GEN-END:variables
    class ScriptTester implements Runnable
    {
        public void run() {
            while(running)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
                if(scriptChanged)
                {
                    scriptChanged = false;
                    String r = compileTest();
                    if(r == null)
                    {
                        statusLabel.setIcon(checkIcon);
                        statusLabel.setForeground(green);
                        statusLabel.setText("No errors");
                    }
                    else
                    {
                        statusLabel.setIcon(xIcon);
                        statusLabel.setForeground(red);
                        statusLabel.setText(r);
                    }
                }
            }
        }
    }
}
